home *** CD-ROM | disk | FTP | other *** search
/ BMUG Revelations / BMUG Revelations.toast / Utilities / Network / Asynchronous Networking / ULACS.p < prev   
Text File  |  1990-12-21  |  26KB  |  753 lines

  1. { Copyright © 1988 - 1990 by Apple Computer, Inc. All rights reserved. }
  2.  
  3. unit ULACS;
  4.  
  5. interface
  6.  
  7. uses
  8.     { • MacApp }
  9.     UMacApp,
  10.     { • Building Blocks }
  11.     UPrinting, UGridView, UTEView, UDialog,
  12.     { • Required for this unit's interface }
  13.     Sane,
  14.     { • Implementation use }
  15.     ToolUtils, Fonts, Resources, Packages, Notification, AppleTalk, ADSP;
  16.  
  17. const
  18.  
  19. kSignature = 'rumo';                        { Application signature }
  20.  
  21. kLACSSettings = 'rums';                { File type for settings/messages file. }
  22.  
  23. kApplicationVersion = '1.1';            { Application version for Params query replies. }
  24.  
  25. { Periodic function times: }
  26.  
  27. { About box "psssts": }
  28. kPssstInitial = 30;
  29. kPssstInactive = 30;
  30. kPssstActive = 30;
  31.  
  32. { Document saver: }
  33. kDocSaverInitial = 60*60*30;
  34. kDocSaverInactive = 60*60*30;
  35. kDocSaverActive = 30;
  36.  
  37. { LACS expirer: }
  38. kExpirerInitial = 30;
  39. kExpirerInactive = 30;
  40. kExpirerActive = 30;
  41.  
  42. { Zone lookup: }
  43. kZoneLookupInitial = 0;
  44. kZoneLookupInactive = 60*60*60*4;
  45. kZoneLookupActive = 30;
  46.  
  47. { Node lookup: }
  48. kNodeLookupInitial = 60*8;
  49. kNodeLookupFastInactive = 60*8;
  50. kNodeLookupSlowInactive = 60*60*20;
  51. kNodeLookupActive = 30;
  52.  
  53. { Gossipee: }
  54. kGossipeeInitial = 0;
  55. kGossipeeInactive = 60*60 + 13;
  56. kGossipeeActive = 30;
  57.  
  58. { Gossiper: }
  59. kGossiperInitial = 1300;
  60. kGossiperInactive = 60*30 + 27;
  61. kGossiperActive = 30;
  62.  
  63. kMessagesWindow = 1000;            { Resource # for messages window. }
  64. kNewWindow = 1001;                    { Resource # for New window. }
  65. kStatusWindow = 1002;                { Resource # for Status window. }
  66. kAboutWindow = 1003;                    { Resource # for About... window. }
  67.  
  68. kPreferencesWindow = 1004;        { Resource # for preferences dialog. }
  69.  
  70. kMySmallIcon = 1000;                    { Resource # for small icon for notification manager. }
  71.  
  72. kOurMemReserve = 20480;            { How much memory to reserve above the MacApp reserve. }
  73. kMaxMessageSize = 500;                { Maximum size of message text. }
  74.  
  75. kSettingsFileSTR = 1000;                { Resource # for STR for default settings file name. }
  76.  
  77. phInvalidSettings = 1000;                { Resource # for invalid settings file alert. }
  78. phNoADSP = 1001;                        { Resource # for no ADSP alert. }
  79. phAreYouSure = 1002;                    { Resource # for querying if the user is really sure about the post. }
  80. phLegal = 1003;                            { Resource # for opening splash screen for legal disclaimers. }
  81. phNoPhase2 = 1004;                        { Resource # for no AppleTalk phase 2 alert. }
  82.  
  83. kPsstHead = 1000;                        { Resource # for "pssst" balloon icon. }
  84. kNoPsstHead = 1001;                    { Resource # for balloon with no "pssst" icon. }
  85.  
  86. kSettingsVersion = 107;                { Version of settings file we recognize. }
  87.  
  88. cMessagesWindow = 1000;            { Command # for Messages Window. }
  89. cNewWindow = 1001;                    { Command # for New Window. }
  90. cStatusWindow = 1002;                { Command # for Status Window. }
  91.  
  92. cMarkAllRead = 1003;                    { Command # for Mark All Messages Read. }
  93. cClearMessages = 1004;                { Command # for Delete All Messages. }
  94.  
  95. cPreferences = 1005;                    { Command # for Preferences... }
  96.  
  97. kStatStrings = 1000;                    { Resource # for STR# strings for status display: }
  98.  
  99. kChooserName = -16096;                { Resource # for Chooser name STR. }
  100.  
  101. kStatBored = 1;                            { "Bored and idle..." }
  102. kStatNewMessage = 2;                    { "Adding new message..." }
  103. kStatZoneUpdate = 3;                    { "Updating zone list..." }
  104. kStatNodeUpdate = 4;                    { "Updating node list..." }
  105. kStatGossiping = 5;                        { "Initiating gossip..." }
  106. kStatIncomingConnect = 6;            { "Gossiping..." }
  107.  
  108. kStatusBoredRate = 5*60;            { How long to leave status up before going bored again (in ticks). }
  109.  
  110. { Network stuff: }
  111.  
  112. { csCodes for new .XPP driver calls: }
  113. xCall = 246;
  114.  
  115. { xppSubCodes: }
  116. zipGetLocalZones = 5;
  117. zipGetZoneList = 6;
  118. zipGetMyZone = 7;
  119.  
  120. type
  121.  
  122. { Offsets for xCall queue elements:  }
  123. xCallParam =
  124.     packed record
  125.         qLink: QElemPtr;
  126.         qType: INTEGER;
  127.         ioTrap: INTEGER;
  128.         ioCmdAddr: Ptr;
  129.         ioCompletion: ProcPtr;
  130.         ioResult: OsErr;
  131.         ioNamePtr: StringPtr;
  132.         ioVRefNum: INTEGER;
  133.         ioRefNum: INTEGER;
  134.         csCode: INTEGER;
  135.         xppSubCode: INTEGER;
  136.         xppTimeOut: Byte;
  137.         xppRetry: Byte;
  138.         filler: INTEGER;
  139.         zipBuffPtr: Ptr;
  140.         zipNumZones: INTEGER;
  141.         zipLastFlag: INTEGER;
  142.         zipInfoField: packed array[1..70] of Byte;
  143.     end;
  144.  
  145. xCallPtr = ^xCallParam;
  146.  
  147. const
  148.  
  149. kXPPTimeOutVal = 3;                    { Re-try XPP attempt every 3 seconds. }
  150. kXPPRetryCount = 5;                    { For five times. }
  151. kZonesBufferSize = 578;                { Size of buffer for zone names. }
  152. kMaxZones = 100;                        { Maximum number of zones to handle. }
  153.  
  154. kMaxNodes = 10;                            { Maximum number of nodes to gossip with at once. }
  155. kNBPTimeOutVal = 8;                    { Re-try NBP PLookupName every 64/60ths seconds. }
  156. kNBPRetryCount = 5;                    { For five times. }
  157. kMaxLookupNames = 100;                { Maximum number of names to lookup. }
  158. kLookupBufferSize = kMaxLookupNames*(sizeof(EntityName)+sizeof(AddrBlock)+4);
  159. kLACS = 'LACS';                            { NBP type for LACSs. }
  160.  
  161. kADSPSendBufSize = 1024;            { Buffer size for ADSP sends. }
  162. kADSPRecvBufSize = 1024;            { Buffer size for ADSP receives. }
  163. kADSPMaxCommand = 1024;        { Buffer size for message exchange protocol command. }
  164.  
  165. kNormalFilter = 'Rumor';                { Normal value for the filter field in messages. }
  166. kNormalType = 'General';                { Normal value for the type field in messages. }
  167.  
  168. kSignatureSeparator = '∫';            { Character used to separate the signature from the message text. }
  169.  
  170. kTab = 9;                                        { ASCII tab. }
  171. kReturn = 13;                                { ASCII carriage return. }
  172.  
  173. type
  174.  
  175. TLACSApplication    = object(TApplication)
  176.  
  177.     function TLACSApplication.DoMakeDocument(itsCmdNumber: CmdNumber): TDocument; override;
  178.         { Make a new document. }
  179.  
  180.     function TLACSApplication.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; override;
  181.         { Handle menu commands. }
  182.  
  183.     procedure TLACSApplication.DoSetupMenus; override;
  184.         { Enable the appropriate menus. }
  185.  
  186.     procedure TLACSApplication.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  187.                                         fieldType: integer)); override;
  188.  
  189.     procedure TLACSApplication.Free; override;
  190.         { Free the application. }
  191.  
  192.     procedure TLACSApplication.ILACSApplication(itsMainFileType: OSType);
  193.         { Initializes the application and globals. }
  194.  
  195.     procedure TLACSApplication.Terminate; override;
  196.         { Clean up when application is terminated. }
  197.  
  198.     end;
  199.  
  200. { Document-wide configuration: }
  201.  
  202. ForwardOn = (kForwardManually, kForwardIfSigned, kForwardAlways);
  203.  
  204. SignatureFrom = (kNoSignature, kSignatureFromChooser, kSignatureFromUser);
  205.  
  206. ConfigSettings =
  207.     record
  208.         inZoneSearch: integer;            { Will look outside our zone with 1/gInZoneSearch probability. }
  209.         push: boolean;                        { Actively connect when a hot message is available. }
  210.         pull: boolean;                        { Connect and ask for hot messages even if we don't have any. }
  211.         pullOnLess: integer;                { Pull if there's less than gPullOnLess messages in our list. }
  212.         count: boolean;                        { Decide on cooling based on count rather than probability. }
  213.         countValue: integer;                { Number of counts or kill with 1/gCountValue probability. }
  214.         feedback: boolean;                { Use information on whether the message has been seen by other end. }
  215.         delayBase: longInt;                { Seconds for base of delay calculations. }
  216.         delayExp: longInt;                    { Exponent for delay calcs: (badPasses*delayBase)^delayExp. }
  217.         expireIn: longInt;                    { Distance in future to expire messages. }
  218.         defaultFilter: Str32;                { Default filter string. }
  219.         defaultType: Str32;                { Default type string. }
  220.         forwarding: ForwardOn;        { When to forward messages. }
  221.         signature: SignatureFrom;    { Where to get the signature. }
  222.         userSignature: Str32;            { Signature the user entered. }
  223.     end;
  224.  
  225. { Saved display state: }
  226.  
  227. DisplayState =
  228.     record
  229.         messagesWindPos: Point;        { Position of Messages window. }
  230.         messagesWindShown: boolean;    { Whether Messages window is shown. }
  231.         notifyOnNew: boolean;            { Whether the "Notify on new" checkbox is set. }
  232.         newWindPos: Point;                { Position of New window. }
  233.         newWindShown: boolean;        { Whether New window is shown. }
  234.         statusWindPos: Point;            { Position of Status window. }
  235.         statusWindShown: boolean;    { Whether Status window is shown. }
  236.         totalMessages: longInt;            { Total message count. }
  237.         passedMessages: longInt;        { Total passed on message count. }
  238.     end;
  239.  
  240. TLACSDocument = object(TDocument)
  241.     fMessages: TList;                                        { All known messages. }
  242.     fMessagesWindow: TMessagesWindow;        { Window to display messages. }
  243.     fNewWindow: TNewWindow;                        { Window to create new messages. }
  244.     fStatusWindow: TStatusWindow;                { Window to display status. }
  245.     fDocumentSaver: TDocumentSaver;            { Periodic document saver object. }
  246.     fMessagesExpirator: TMessagesExpirator;    { Message expiration object. }
  247.     fZoneLooker: TZoneLookup;                        { Zone lookup object. }
  248.     fNodeLooker: TNodeLookup;                        { Node lookup object. }
  249.     fGossiper: TGossip;                                    { Gossiper (spreader). }
  250.     fGossipee: TGossip;                                    { Gossipee (receiver). }
  251.     fConfig: ConfigSettings;                            { Distribution algorithm parameters. }
  252.     fUseDisplayState: boolean;                        { True if we're to use the display state record. }
  253.     fDisplayState: DisplayState;                        { The positions of the windows. }
  254.  
  255.     procedure TLACSDocument.CheckFreeSpace;
  256.         { Check the amount of free space available in memory, and free messages if necessary to make room. }
  257.  
  258.     procedure TLACSDocument.CloseView(aView: TView); override;
  259.         { Close a window in the document. }
  260.  
  261.     procedure TLACSDocument.DoInitialState; override;
  262.         { Set up the initial state of the document. }
  263.  
  264.     procedure TLACSDocument.DoMakeViews(forPrinting: boolean); override;
  265.         { Create views to display the document. }
  266.  
  267.     function TLACSDocument.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; override;
  268.         { Handle menu commands. }
  269.  
  270.     procedure TLACSDocument.DoNeedDiskSpace(var dataForkBytes, rsrcForkBytes: longInt); override;
  271.         { Computer how much disk space is needed to save the document to disk. }
  272.  
  273.     procedure TLACSDocument.DoRead(aRefNum: integer; rsrcExists, forPrinting: boolean); override;
  274.         { Read the document from disk. }
  275.  
  276.     procedure TLACSDocument.DoSetupMenus; override;
  277.         { Enable the appropriate menus. }
  278.  
  279.     procedure TLACSDocument.DoWrite(aRefNum: integer; makingCopy: boolean); override;
  280.         { Write the document to disk. }
  281.  
  282.     procedure TLACSDocument.ExpireMessages;
  283.         { Check for expired messages, and dump them if they are expired. }
  284.  
  285.     procedure TLACSDocument.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  286.                                         fieldType: integer)); override;
  287.  
  288.     procedure TLACSDocument.Free; override;
  289.         { Free the document. }
  290.  
  291.     function TLACSDocument.GetHotMessage: TMessage;
  292.         { Find a hot message, if there are any. }
  293.  
  294.     procedure TLACSDocument.GetPreferences;
  295.         { Query the user for his preferences. }
  296.  
  297.     function TLACSDocument.GetRandomMessage: TMessage;
  298.         { Find a message at random. }
  299.  
  300.     function TLACSDocument.GetMessage(f: Str32; t: Str32; h: Handle): TMessage;
  301.         { Get the message that corresponds to the filter/type/handle given. }
  302.  
  303.     function TLACSDocument.HandleIncomingCommand(theData: Ptr; theSz: longInt): longInt;
  304.         { Parse and process an incoming command. }
  305.  
  306.     procedure TLACSDocument.ILACSDocument;
  307.         { Intialize the document. }
  308.  
  309.     procedure TLACSDocument.MarkAllAsRead;
  310.         { Mark all messages as read. }
  311.  
  312.     procedure TLACSDocument.NewMessage(ru: boolean; f: Str32; t: Str32; h: Handle; sd: longInt; ed: longInt;
  313.                                                                     alwaysForward: boolean);
  314.         { Enter a new message into the document. }
  315.  
  316.     procedure TLACSDocument.ParseAsParams(h: Handle);
  317.         { Interpret the data in the handle as a configuration setting string. }
  318.  
  319.     procedure TLACSDocument.ShowWindows; override;
  320.         { Display windows (or not) as appropriate. }
  321.  
  322.     end;
  323.  
  324. { Format of a message when saved to disk (discluding text): }
  325.  
  326. SavedMessage =
  327.     record
  328.         hot: boolean;
  329.         successfulPasses: integer;
  330.         badPasses: integer;
  331.         filter: Str32;
  332.         rType: Str32;
  333.         startDate: longInt;
  334.         expireDate: longInt;
  335.         lastMessaged: longInt;
  336.         inReadList: boolean;
  337.         forward: boolean;
  338.     end;
  339.  
  340. TMessage = object(TObject)
  341.     fDocument: TLACSDocument;            { The document containing the message. }
  342.     fHot: boolean;                                    { Whether the message is currently hot. }
  343.     fSuccessfulPasses: integer;                { How many times we've successfully passed the message on. }
  344.     fBadPasses: integer;                            { How many times we've unsuccessfully tried to pass it on. }
  345.     fFilter: Str32;                                    { The message's filter field. }
  346.     fType: Str32;                                    { The message's type field. }
  347.     fText: Handle;                                    { The body of the message. }
  348.     fStartDate: longInt;                            { The origination date of the message. }
  349.     fExpireDate: longInt;                            { The expiration date of the message. }
  350.     fLastMessaged: longInt;                    { The last time we passed it on, or tried to. }
  351.     fForward: boolean;                            { Whether this message has been approved for forwarding. }
  352.  
  353.     procedure TMessage.AsString(var aString: Str255);
  354.         { Return a string that represents the message (for display lists). }
  355.  
  356.     function TMessage.BuildMessageCommand(var theData: Ptr): longInt;
  357.         { Build a message command into the buffer pointed to by theData, incrementing theData as we go,
  358.             and return the size of the command built. }
  359.  
  360.     procedure TMessage.DoNeedDiskSpace(var dataForkBytes, rsrcForkBytes: longInt);
  361.         { Return the amount of disk space needed to save this message. }
  362.  
  363.     procedure TMessage.FailedPass;
  364.         { Factor in one more bad pass attempt. }
  365.  
  366.     procedure TMessage.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  367.                                         fieldType: integer)); override;
  368.  
  369.     procedure TMessage.Free; override;
  370.         { Free the message object. }
  371.  
  372.     procedure TMessage.IMessage(aDoc: TLACSDocument; isRead: boolean; f: Str32; t: Str32; newText: Handle;
  373.                                                 sd: longInt; ed: longInt);
  374.         { Initialize a message object. }
  375.  
  376.     procedure TMessage.IMessageFromFile(aDoc: TLACSDocument; aRefNum: integer);
  377.         { Initialize a message object from a file. }
  378.  
  379.     function TMessage.IsHot: boolean;
  380.         { Return true if this message is still hot, and if enough time has passed for it to be spread again. }
  381.  
  382.     procedure TMessage.MarkAsRead;
  383.         { Mark this message as read. }
  384.  
  385.     procedure TMessage.ParseAsParams;
  386.         { Parse ourself as algorithm parameters. }
  387.  
  388.     procedure TMessage.SuccessfullPass;
  389.         { Factor in one more successfull pass attempt. }
  390.  
  391.     procedure TMessage.UpdateHotness;
  392.         { Update the temperature of this message. }
  393.  
  394.     procedure TMessage.WriteToFile(aRefNum: integer);
  395.         { Save this message to disk. }
  396.  
  397.     end;
  398.  
  399. TDisplayList = object(TSortedList)
  400.     fDocument: TLACSDocument;                { Our document. }
  401.     fView: TTextListView;                            { The corresponding text list view. }
  402.  
  403.     procedure TDisplayList.AtDelete(index: ArrayIndex); override;
  404.         { Delete the entry at index. }
  405.  
  406.     function TDisplayList.Compare(item1, item2: TObject): CompareResult; override;
  407.         { Compare two objects. }
  408.  
  409.     procedure TDisplayList.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  410.                                         fieldType: integer)); override;
  411.  
  412.     procedure TDisplayList.FreeAll; override;
  413.         { Free everything. }
  414.  
  415.     procedure TDisplayList.IDisplayList(theDoc: TLACSDocument; theView: TMessageListView);
  416.         { Initialize the list. }
  417.  
  418.     procedure TDisplayList.Insert(item: TObject); override;
  419.         { Insert an item into the list. }
  420.  
  421.     procedure TDisplayList.Invalidate(o: TObject);
  422.         { Invalidate the displayed object. }
  423.  
  424.     procedure TDisplayList.Select(o: TObject);
  425.         { Select the displayed object. }
  426.  
  427.     end;
  428.  
  429. TMessagesWindow = object(TWindow)
  430.     fNotification: ^NMRec;                        { Notification manager record. }
  431.     fUnread: TDisplayList;                        { List of unread messages. }
  432.     fRead: TDisplayList;                            { List of read messages. }
  433.     fNotify: TCheckBox;                            { Checkbox that indicates whether to notify on new messages. }
  434.     fShow: TTEView;                                { View to display the message text in. }
  435.     fOriginated: TStaticText;                    { View for origination date. }
  436.     fExpires: TStaticText;                        { View for expiration date. }
  437.     fForward: TCheckbox;                        { Whether to forward this message on. }
  438.  
  439.     procedure TMessagesWindow.ClearCurrent;
  440.         { Clear out the selected message display. }
  441.  
  442.     procedure TMessagesWindow.DisplayMessage(r: TMessage);
  443.         { Display message r. }
  444.  
  445.     procedure TMessagesWindow.DoChoice(origView: TView; itsChoice: integer); override;
  446.         { Handle button hits, etc. }
  447.  
  448.     procedure TMessagesWindow.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  449.                                         fieldType: integer)); override;
  450.  
  451.     procedure TMessagesWindow.FindSubviews;
  452.         { Lookup all our subviews for later. }
  453.  
  454.     procedure TMessagesWindow.Free; override;
  455.         { Free the window. }
  456.  
  457.     procedure TMessagesWindow.KillNotify;
  458.         { Take away the Notification Manager notification. }
  459.  
  460.     procedure TMessagesWindow.Notify;
  461.         { Notify the user via the Notification Manager. }
  462.  
  463.     end;
  464.  
  465. TNewWindow = object(TWindow)
  466.     fInput: TTEView;                                { View for typing message body. }
  467.     fSpread: TButton;                                { Send Message button. }
  468.     fMonth: TPopup;                                { Expiration month pop-up. }
  469.     fDay: TPopup;                                    { Expiration day pop-up. }
  470.     fYear: TStaticText;                            { Expiration year display (computed). }
  471.     fSignature: TStaticText;                    { The message signature. }
  472.  
  473.     procedure TNewWindow.DoChoice(origView: TView; itsChoice: integer); override;
  474.         { Handle button hits, etc. }
  475.  
  476.     function TNewWindow.DoKeyCommand(ch: char; aKeyCode: integer;
  477.                                                                 var info: EventInfo): TCommand; override;
  478.         { Handle keyboard events. }
  479.  
  480.     function TNewWindow.ExpireExpired: boolean;
  481.         { Check if we need to reset the expiration date. }
  482.  
  483.     procedure TNewWindow.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  484.                                         fieldType: integer)); override;
  485.  
  486.     procedure TNewWindow.FindSubviews;
  487.         { Lookup all our subviews for later. }
  488.  
  489.     function TNewWindow.GetExpire: longInt;
  490.         { Get the expiration date. }
  491.  
  492.     procedure TNewWindow.GetSetExpire;
  493.         { Get and set the expiration date (corrects for odd month/day combinations, etc. }
  494.  
  495.     procedure TNewWindow.GetSignature;
  496.         { Figure out the current signature. }
  497.  
  498.     procedure TNewWindow.ResetExpire;
  499.         { Reset the expiration date display. }
  500.  
  501.     procedure TNewWindow.ResetIfExpired;
  502.         { Reset the expiration date if the current one is expired. }
  503.  
  504.     procedure TNewWindow.SetExpire(t: longInt);
  505.         { Set the expiration date. }
  506.  
  507.     end;
  508.  
  509. TStatusWindow = object(TWindow)
  510.     fTotalMessages: TNumberText;                { Total messages display. }
  511.     fTotalPassed: TNumberText;                    { Total passed on messages display. }
  512.     fHotMessages: TNumberText;                { Current hot messages display. }
  513.     fColdMessages: TNumberText;                { Current cold messages display. }
  514.     fGossipWith: array [1..kMaxNodes] of TStaticText;    { Gossiping with... display. }
  515.     fStatus: TStaticText;                            { Statis display. }
  516.     fLastStatusChange: longInt;                    { Last status change time. }
  517.  
  518.     procedure TStatusWindow.Bored;
  519.         { Change status to "bored and idle..." }
  520.  
  521.     procedure TStatusWindow.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  522.                                         fieldType: integer)); override;
  523.  
  524.     procedure TStatusWindow.FindSubviews;
  525.         { Lookup all our subviews for later. }
  526.  
  527.     procedure TStatusWindow.IncColdMessages(i: integer);
  528.         { Increment the current cold messages count by i. }
  529.  
  530.     procedure TStatusWindow.IncHotMessages(i: integer);
  531.         { Increment the current hot messages count by i. }
  532.  
  533.     procedure TStatusWindow.IncTotalPassed(i: integer);
  534.         { Increment the total messages passed on count by i. }
  535.  
  536.     procedure TStatusWindow.IncTotalMessages(i: integer);
  537.         { Increment the total messages seen count by i. }
  538.  
  539.     procedure TStatusWindow.SetStatus(statNum: integer);
  540.         { Change the status display. }
  541.  
  542.     procedure TStatusWindow.UpdateGossipWith;
  543.         { Update the display of who we're gossiping with. }
  544.  
  545.     end;
  546.  
  547. TMessageListView = object(TTextListView)
  548.     fWindow: TMessagesWindow;                { The window we're in. }
  549.     fList: TDisplayList;                                { The cooresponding list of messages. }
  550.  
  551.     function TMessageListView.DoMouseCommand(var theMouse: Point; var info: EventInfo;
  552.                                                                         var hysteresis: Point): TCommand; override;
  553.         { Handle mouse events. }
  554.  
  555.     procedure TMessageListView.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  556.                                         fieldType: integer)); override;
  557.  
  558.     procedure TMessageListView.GetItemText(anItem: integer; var aString: Str255); override;
  559.         { Retrieve the text for a particular item. }
  560.  
  561.     end;
  562.  
  563. { Valid states for TPeriodic's fState: }
  564.  
  565. PeriodicStates = (kPeriodicInactive, kPeriodicWaiting, kPeriodicActive);
  566.  
  567. TPeriodic = object(TEvtHandler)
  568.     fInactiveIdle: longInt;                            { How long to idle between activates. }
  569.     fActiveIdle: longInt;                                { How long to idle between checks for async completion. }
  570.     fState: PeriodicStates;                            { The current state. }
  571.  
  572.     procedure TPeriodic.Activate;
  573.         { Start a periodic activity. }
  574.  
  575.     function TPeriodic.DoIdle(phase: IdlePhase): boolean; override;
  576.         { Internal method -- idle the object. }
  577.  
  578.     procedure TPeriodic.DoIt;
  579.         { Handle the results of an async operation. }
  580.  
  581.     procedure TPeriodic.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  582.                                         fieldType: integer)); override;
  583.  
  584.     procedure TPeriodic.Free; override;
  585.         { Free the object. }
  586.  
  587.     procedure TPeriodic.IPeriodic(initialIdle, inactiveIdle, activeIdle: longInt);
  588.         { Initialize the object. }
  589.  
  590.     procedure TPeriodic.Kick;
  591.         { Start things up even if it isn't normally time yet. }
  592.  
  593.     procedure TPeriodic.Waiting;
  594.         { Test for async completion. }
  595.  
  596.     end;
  597.  
  598. TPssst = object(TPeriodic)
  599.  
  600.     procedure TPssst.Activate; override;
  601.         { Update the about box. }
  602.  
  603.     end;
  604.  
  605. TMessagesExpirator = object(TPeriodic)
  606.     fDocument: TLACSDocument;                    { The document we're expiring. }
  607.  
  608.     procedure TMessagesExpirator.Activate; override;
  609.         { Expire message. }
  610.  
  611.     procedure TMessagesExpirator.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  612.                                         fieldType: integer)); override;
  613.  
  614.     procedure TMessagesExpirator.IMessagesExpirator(aDoc: TLACSDocument; 
  615.                                                                                 initialIdle, inactiveIdle, activeIdle: longInt);
  616.         { Initialize messages expirer. }
  617.  
  618.     end;
  619.  
  620. TDocumentSaver = object(TPeriodic)
  621.     fDocument: TLACSDocument;                    { The document we're saving. }
  622.  
  623.     procedure TDocumentSaver.Activate; override;
  624.         { Get ready to save. }
  625.  
  626.     procedure TDocumentSaver.DoIt; override;
  627.         { Save the document. }
  628.  
  629.     procedure TDocumentSaver.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  630.                                         fieldType: integer)); override;
  631.  
  632.     procedure TDocumentSaver.IDocumentSaver(aDoc: TLACSDocument; 
  633.                                                                                 initialIdle, inactiveIdle, activeIdle: longInt);
  634.         { Initialize the document saver. }
  635.  
  636.     procedure TDocumentSaver.Waiting; override;
  637.         { Wait until we're in the foreground. }
  638.  
  639.     end;
  640.  
  641. TZoneLookup = object(TPeriodic)
  642.     fDocument: TLACSDocument;                    { The document we're looking up for. }
  643.     fZoneCount: integer;                                    { How many zones we've found. }
  644.     fXPPPBPtr: xCallPtr;                                { XPP parameter block. }
  645.     fZonesBuffer: Ptr;                                    { Input buffer. }
  646.     fOurZone: Str32;                                        { The name of our own zone. }
  647.     fZones: array [1..kMaxZones] of Str32;    { Zone names. }
  648.  
  649.     procedure TZoneLookup.Activate; override;
  650.         { Start a zone list lookup. }
  651.  
  652.     procedure TZoneLookup.DoIt; override;
  653.         { Process returned zone list. }
  654.  
  655.     function TZoneLookup.GetRandomZone: Str32;
  656.         { Pick a random zone from the list and return it. }
  657.  
  658.     procedure TZoneLookup.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  659.                                         fieldType: integer)); override;
  660.  
  661.     procedure TZoneLookup.Free; override;
  662.         { Free the zone lookup object. }
  663.  
  664.     procedure TZoneLookup.IZoneLookup(aDoc: TLACSDocument; initialIdle, inactiveIdle, activeIdle: longInt);
  665.         { Initialize the zone lookup object. }
  666.  
  667.     procedure TZoneLookup.Waiting; override;
  668.         { Wait for the zone lookup to complete. }
  669.  
  670.     end;
  671.  
  672. TNodeLookup = object(TPeriodic)
  673.     fDocument: TLACSDocument;                    { The document we're looking up for. }
  674.     fSlowIdle: longInt;                                    { Slow idling speed. }
  675.     fFastIdle: longInt;                                        { Fast idling speed. }
  676.     fNodeCount: integer;                                    { How many nodes we've found. }
  677.     fNameBuffer: Ptr;                                    { Input buffer pointer. }
  678.     fpBlock: MPPPBPtr;                                    { IO block pointer. }
  679.     fLookupBuf: Ptr;                                        { Lookup buffer pointer. }
  680.     fZone: Str32;                                            { The zone we're currently looking in. }
  681.     fNodes: array [1..kMaxNodes] of EntityName;    { Nodes we've found. }
  682.     fAddrs: array [1..kMaxNodes] of AddrBlock;        { Addresses we've found. }
  683.  
  684.  
  685.     procedure TNodeLookup.Activate; override;
  686.         { Start a node lookup. }
  687.  
  688.     procedure TNodeLookup.DoIt; override;
  689.         { Process the results of a node lookup. }
  690.  
  691.     procedure TNodeLookup.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  692.                                         fieldType: integer)); override;
  693.  
  694.     procedure TNodeLookup.Free; override;
  695.         { Free the node lookup object. }
  696.  
  697.     function TNodeLookup.GetRandomNode(var addr: AddrBlock): boolean;
  698.         { Pick a random node from the list and return it. GetRandomNode itself returns true if we had a node to return. }
  699.  
  700.     procedure TNodeLookup.INodeLookup(aDoc: TLACSDocument; initialIdle, fastIdle, slowIdle, activeIdle: longInt);
  701.         { Initialize the node lookup object. }
  702.  
  703.     procedure TNodeLookup.Waiting; override;
  704.         { Wait for a node lookup to complete. }
  705.  
  706.     end;
  707.  
  708. TGossip = object(TPeriodic)
  709.     fDocument: TLACSDocument;                    { The document we're gossiping in. }
  710.     fOutgoing: boolean;                                    { Whether this is an outgoing gossiper. }
  711.     fDidPull: boolean;                                        { Whether we just did a pull. }
  712.     fADSPSocket: integer;                                { Our socket number. }
  713.     fADSP: DSPPBPtr;                                    { The ADSP IO block pointer. }
  714.     fCcbPtr: Ptr;                                            { CCB for ADSP. }
  715.     fSendQueue: Ptr;                                        { Send queue for ADSP. }
  716.     fRecvQueue: Ptr;                                        { Receive queue for ADSP. }
  717.     fAttnPtr: Ptr;                                            { Attn ptr for ADSP. }
  718.     fADSPData: Ptr;                                        { The data buffer pointer. }
  719.     fNTE: ^NamesTableEntry;                            { Our names table entry. }
  720.  
  721.  
  722.     procedure TGossip.Activate; override;
  723.         { Start a new gossip session (outgoing only). }
  724.  
  725.     procedure TGossip.DoIt; override;
  726.         { Handle new input. }
  727.  
  728.     procedure TGossip.Fields(procedure DoToField(fieldName: Str255; fieldAddr: Ptr;
  729.                                         fieldType: integer)); override;
  730.  
  731.     procedure TGossip.Free; override;
  732.         { Free the gossip object. }
  733.  
  734.     procedure TGossip.IGossip(aDoc: TLACSDocument; outgoing: boolean; initialIdle, inactiveIdle, activeIdle: longInt);
  735.         { Initialize the gossip object. }
  736.  
  737.     procedure TGossip.PassiveOpen;
  738.         { Do a passive connection open. }
  739.  
  740.     procedure TGossip.ResetConnection;
  741.         { Reset the connection. }
  742.  
  743.     procedure TGossip.Waiting; override;
  744.         { Wait for more input or a connection to open. }
  745.  
  746.     end;
  747.  
  748. implementation
  749.  
  750.     {$I ULACS.inc1.p}
  751.  
  752. end.
  753.